// $URL: http://mingw-lib.googlecode.com/svn/trunk/working/avcodec_to_widget_9/t_box_player_ctx.h $
// $Rev: 320 $
// $Author: akio.miyoshi $
// $Date:: 2010-07-31 10:13:06 +0000#$

#ifndef T_BOX_PLAYER_H
#define T_BOX_PLAYER_H

#include "stable.h"
#include "t_box.h"
#include "t_av_packet.h"
#include "t_generator.h" //==> t_box_audio.h
#include "t_box_input.h"
#include "t_box_bar.h"
#include "t_video_frame.h"

class T_Box_Player_Packet_Thread : public T_Box_Thread
{
protected:
    T_Box_Player_Context *m_player_ctx;
public:
    explicit T_Box_Player_Packet_Thread(T_Box_Player_Context *a_player_ctx)
        : m_player_ctx(a_player_ctx)
    {
    }
protected:
    virtual void run();
};

class T_Box_Player_Decode_Thread : public T_Box_Thread
{
protected:
    T_Box_Player_Context *m_player_ctx;
public:
    explicit T_Box_Player_Decode_Thread(T_Box_Player_Context *a_player_ctx)
        : m_player_ctx(a_player_ctx)
    {
    }
protected:
    virtual void run();
};

struct T_Box_Stream_Info
{
    bool isValid;
    int stream_index;
    AVCodecContext *codec_ctx;
    AVCodec *codec;
    AVStream *stream;
    T_AV_Packet_Queue packet_queue;
    explicit T_Box_Stream_Info(T_Box_Player_Context *a_player_ctx, AVMediaType a_media_type);
};

class T_Box_Player_Context : public QObject
{
    Q_OBJECT
public:
    T_Box_Input *m_box_input;
    AVFormatContext *m_format_ctx;
    T_Box_Stream_Info m_audio;
    T_Box_Stream_Info m_video;
    T_Stopwatch m_stopwatch;
    QAudioOutput *m_audioOutput;
    T_Generator *m_generator;
    DECLARE_ALIGNED(16,quint8,m_audio_decode_array)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
    DECLARE_ALIGNED(16,quint8,m_audio_convert_array)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
    T_VideoProgressBar *m_seek_bar;
    T_BufferProgressBar *m_buffering_bar;
    ////T_Video_Frame_Queue m_frame_queue;
public:
    explicit T_Box_Player_Context(class T_Box_Input *a_box_input, AVFormatContext *a_format_ctx);
    ~T_Box_Player_Context();
    void setAudioOutput(QAudioOutput *a_audioOutput)
    {
        m_audioOutput = a_audioOutput;
    }
    T_AV_Packet *readPacket();
    T_AV_Packet *enqueuePacket();
    qint64 duration()
    {
        return  ((qint64)1000) * this->m_format_ctx->duration / AV_TIME_BASE;
    }
    QString durationToString(const QString &a_format)
    {
        QTime v_duration_clock(0, 0, 0, 0);
        v_duration_clock = v_duration_clock.addMSecs(this->duration());
        return v_duration_clock.toString(a_format);
    }
    bool needBuffering()
    {
#if 0x0
        if(m_video.packet_queue.duration()<T_Box::PLAYER_BUFFER_TIME)
        {
            return true;
        }
#endif
#if USE_DECODE_THREAD
        for(int i=0; i<m_video.packet_queue.size(); i++)
        {
            if(i>=T_Box::PLAYER_AHEAD_IMAGE)
            {
                break;
            }
            if(!m_video.packet_queue.value(i)->isDecoded())
            {
                //qDebug() << "[not decoded]" << i;
                return true;
            }
        }
#endif
        if(m_video.packet_queue.duration(m_stopwatch.elapsed())<T_Box::PLAYER_BUFFER_TIME)
        {
            return true;
        }
        return false;
    }
    T_Box_Seek_Manager *seekManager()
    {
        return &m_seek_manager;
    }
    bool handleSeek();
    void start()
    {
        Q_ASSERT(!m_packet_thread);
        m_packet_thread = new T_Box_Player_Packet_Thread(this);
        m_packet_thread->start();
        Q_ASSERT(!m_decode_thread);
        m_decode_thread = new T_Box_Player_Decode_Thread(this);
        m_decode_thread->start();
    }
    void finish()
    {
        qDebug() << "[T_Box_Player_Context::finish(1)]";
        if(m_packet_thread) m_packet_thread->finish();
        qDebug() << "[T_Box_Player_Context::finish(2)]";
        if(m_decode_thread) m_decode_thread->finish();
        qDebug() << "[T_Box_Player_Context::finish(3)]";
    }

protected:
    qint64 seek(qint64 a_msec);
protected:
    T_Box_Seek_Manager m_seek_manager;
    T_Box_Player_Packet_Thread *m_packet_thread;
    T_Box_Player_Decode_Thread *m_decode_thread;
public: //FIXME
    T_AVPicture_Resizable m_resize_pic;
};

#endif // T_BOX_PLAYER_H
